package com.walleipt.ipt_tools.utils;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.net.ssl.SSLContext;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpRequest;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class HttpClientPool {

    private static final Logger LOG = LoggerFactory.getLogger(HttpClientPool.class);
	
    private final static int TIME_OUT = 800;
    private static PoolingHttpClientConnectionManager clientConnectionManager;
    private static CloseableHttpClient httpClient;
    private static RequestConfig config = RequestConfig.custom()
									            .setConnectionRequestTimeout(TIME_OUT)
									            .setConnectTimeout(TIME_OUT)
									            .setSocketTimeout(TIME_OUT)
									            .build();
    private final static Object syncLock = new Object();

    static {
        try {
            //添加对https的支持，该sslContext没有加载客户端证书
            // 如果需要加载客户端证书，请使用如下sslContext,其中KEYSTORE_FILE和KEYSTORE_PASSWORD分别是你的证书路径和证书密码
            //KeyStore keyStore  =  KeyStore.getInstance(KeyStore.getDefaultType()
            //FileInputStream instream =   new FileInputStream(new File(KEYSTORE_FILE));
            //keyStore.load(instream, KEYSTORE_PASSWORD.toCharArray());
            //SSLContext sslContext = SSLContexts.custom().loadKeyMaterial(keyStore,KEYSTORE_PASSWORD.toCharArray())
            // .loadTrustMaterial(null, new TrustSelfSignedStrategy())
            //.build();
            SSLContext sslContext = SSLContexts.custom()
                    .loadTrustMaterial(null, new TrustSelfSignedStrategy())
                    .build();
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.getDefaultHostnameVerifier());
            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register("https", sslsf)
                    .register("http", PlainConnectionSocketFactory.getSocketFactory())
                    .build();
            clientConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
            // 最大连接数
            clientConnectionManager.setMaxTotal(1200);
            // 每个路由的基础连接数
            clientConnectionManager.setDefaultMaxPerRoute(25);
        } catch (Exception e) {
            LOG.warn("httpUtils init get exception:", e);
        }
    }

    public static CloseableHttpClient getHttpClient() {
        if (httpClient == null) {
            synchronized (syncLock) {
                if (httpClient == null) {
                    httpClient = HttpClients.custom()
                            .setConnectionManager(clientConnectionManager)
                            .setDefaultRequestConfig(config)
                            .setRetryHandler((e, i, httpContext) -> false)
                            .build();
                }
            }
        }
        return httpClient;
    }

    /**
     * get请求
     *
     * @param _url
     * @param _headers
     * @return
     */
    public static String httpGet(String _url, Map<String, Object> _headers) {
        CloseableHttpClient httpClient = getHttpClient();
        HttpRequest httpGet = new HttpGet(_url);
        if (_headers != null && !_headers.isEmpty()) {
            httpGet = setHeaders(_headers, httpGet);
        }
        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute((HttpGet) httpGet);
            HttpEntity entity = response.getEntity();
            String result = EntityUtils.toString(entity) ;
            LOG.debug( "Invken services : type=Get; _url="+_url+"; _headers="+_headers+"; result="+result );
            return result ;
        } catch (IOException e) {
        	LOG.error("httpUtils httpGet is exception:" + e +"; url : "+_url +"; data: "+_headers.toString());
        }
        return null;
    }
    

    /**
     * post请求,使用json格式传参
     *
     * @param _url
     * @param _headers
     * @param _body
     * @return
     */
    public static String httpPost(String _url, Map<String, Object> _headers, String _body) {
        CloseableHttpClient httpClient = getHttpClient();
        HttpRequest request = new HttpPost(_url);
        if (_headers != null && !_headers.isEmpty()) {
            request = setHeaders(_headers, request);
        }
        CloseableHttpResponse response = null;

        try {
            HttpPost httpPost = (HttpPost) request;
            httpPost.setEntity(new StringEntity(_body, ContentType.create("application/json", "UTF-8")));
            response = httpClient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            String result = EntityUtils.toString(entity);
            LOG.debug( "Invken services : type=Post; _url="+_url+"; _headers="+_headers+"; result="+result );
            return result ;
        } catch (IOException e) {
        	LOG.error("httpUtils httpPost is exception:" + e +"; url : "+_url +"; data: "+_body);
        }
        return null;
    }

    /**
     * 使用表单键值对传参
     */
    public static HttpEntity PostForm(String url, Map<String, Object> headers, List<NameValuePair> data) {
        CloseableHttpClient httpClient = getHttpClient();
        HttpRequest request = new HttpPost(url);
        if (headers != null && !headers.isEmpty()) {
            request = setHeaders(headers, request);
        }
        CloseableHttpResponse response = null;
        UrlEncodedFormEntity uefEntity;
        try {
            HttpPost httpPost = (HttpPost) request;
            uefEntity = new UrlEncodedFormEntity(data, "UTF-8");
            httpPost.setEntity(uefEntity);
            // httpPost.setEntity(new StringEntity(data, ContentType.create("application/json", "UTF-8")));
            response = httpClient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            return entity;
        } catch (IOException e) {
        	LOG.error("httpUtils PostForm is exception:", e);
        }
        return null;
    }

    /**
     * 设置请求头信息
     *
     * @param headers
     * @param request
     * @return
     */
    @SuppressWarnings("unchecked")
	private static HttpRequest setHeaders(Map<String, Object> headers, HttpRequest request) {
        for (Map.Entry<String, Object> entry : headers.entrySet()) {
            if (!entry.getKey().equals("Cookie")) {
                request.addHeader((String) entry.getKey(), (String) entry.getValue());
            } else {
                Map<String, Object> Cookies = (Map<String, Object>) entry.getValue();
                for (Map.Entry<String, Object> entry1 : Cookies.entrySet()) {
                    request.addHeader(new BasicHeader("Cookie", (String) entry1.getValue()));
                }
            }
        }
        return request;
    }

    public static Map<String, String> getCookie(String url) {
        CloseableHttpClient httpClient = getHttpClient();
        HttpRequest httpGet = new HttpGet(url);
        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute((HttpGet) httpGet);
            Header[] headers = response.getAllHeaders();
            Map<String, String> cookies = new HashMap<String, String>();
            for (Header header : headers) {
                cookies.put(header.getName(), header.getValue());
            }
            return cookies;
        } catch (Exception e) {
        	LOG.error("httpUtils getCookie is exception:", e);
        }
        return null;
    }
}

